#ifndef UnstructMG_POINT_JACOBI_HPP
#define UnstructMG_POINT_JACOBI_HPP

#include "par_CSRMatrix.hpp"

template<typename idx_t, typename data_t, typename setup_t, typename calc_t, int dof>
class PointJacobi : public Solver<idx_t, setup_t, calc_t, dof> {
protected:
    bool own_A = false;
    const par_CSRMatrix<idx_t, data_t, calc_t, dof> * A_calc = nullptr;// setup时需要截断的低精度矩阵
    CSRMatrix<idx_t, data_t, calc_t, dof> * w_invDiag = nullptr;
    bool invD_separated = false;

    void truncate();
    void separate_invD(const par_CSRMatrix<idx_t, setup_t, setup_t, dof> & par_ss_A);
    void Mult_ipl(const par_Vector<idx_t, calc_t, dof> & b, par_Vector<idx_t, calc_t, dof> & x) const;
public:
    PointJacobi(const calc_t wgt = 0.7);
    ~PointJacobi();
    void SetOperator(const Operator<idx_t, setup_t, dof> & op);
};

typedef PointJacobi<int, double, double, double, 1> PointJacobi_I32All64_DOF1;
typedef PointJacobi<int, double, double, double, 2> PointJacobi_I32All64_DOF2;
typedef PointJacobi<int, double, double, double, 3> PointJacobi_I32All64_DOF3;
typedef PointJacobi<int, double, double, double, 4> PointJacobi_I32All64_DOF4;

typedef PointJacobi<int, float , double, double, 1> PointJacobi_I32K64P64D32_DOF1;
typedef PointJacobi<int, float , double, double, 2> PointJacobi_I32K64P64D32_DOF2;
typedef PointJacobi<int, float , double, double, 3> PointJacobi_I32K64P64D32_DOF3;
typedef PointJacobi<int, float , double, double, 4> PointJacobi_I32K64P64D32_DOF4;

typedef PointJacobi<int, float , double, float , 1> PointJacobi_I32K64P32D32_DOF1;
typedef PointJacobi<int, float , double, float , 2> PointJacobi_I32K64P32D32_DOF2;
typedef PointJacobi<int, float , double, float , 3> PointJacobi_I32K64P32D32_DOF3;
typedef PointJacobi<int, float , double, float , 4> PointJacobi_I32K64P32D32_DOF4;

typedef PointJacobi<int, float , float , float , 1> PointJacobi_I32All32_DOF1;
typedef PointJacobi<int, float , float , float , 2> PointJacobi_I32All32_DOF2;
typedef PointJacobi<int, float , float , float , 3> PointJacobi_I32All32_DOF3;
typedef PointJacobi<int, float , float , float , 4> PointJacobi_I32All32_DOF4;
#ifdef USE_FP16
typedef PointJacobi<int, __fp16, double, float , 1> PointJacobi_I32K64P32D16_DOF1;
typedef PointJacobi<int, __fp16, double, float , 2> PointJacobi_I32K64P32D16_DOF2;
typedef PointJacobi<int, __fp16, double, float , 3> PointJacobi_I32K64P32D16_DOF3;
typedef PointJacobi<int, __fp16, double, float , 4> PointJacobi_I32K64P32D16_DOF4;

typedef PointJacobi<int, __fp16, float , float , 1> PointJacobi_I32K32P32D16_DOF1;
typedef PointJacobi<int, __fp16, float , float , 2> PointJacobi_I32K32P32D16_DOF2;
typedef PointJacobi<int, __fp16, float , float , 3> PointJacobi_I32K32P32D16_DOF3;
typedef PointJacobi<int, __fp16, float , float , 4> PointJacobi_I32K32P32D16_DOF4;
#endif
#endif